#include <iostream>
#include <cuda_runtime.h>
#include "../common/common.h"
#define DEVICENUM 0

int main(int argc, char **argv)
{
    cudaSetDevice(DEVICENUM);

    int nElem = 1 << 15;
    size_t nbytes = nElem * sizeof(float);

    // 分配固定主机内存
    float *host_pinned_mem = nullptr;
    // 虽然使用cuda开头函数，但该内存还是在host端; 所以 cudaHostAlloc() 实际替换的是malloc
    CHECK(cudaMallocHost((float **)&host_pinned_mem, nbytes));
    initialDataRandom(host_pinned_mem, nElem); // 初始化主机固定内存

    // 分配设备内存
    float *device_mem = nullptr;
    CHECK(cudaMalloc((float **)&device_mem, nbytes));

    // 将主机数据传输到设备
    // 当我们在调用cudaMemcpy(dest, src, ...)时，程序会自动检测dest或者src是否为Pinned Memory，
    // 若不是，则会自动将其内容拷入一不可见的Pinned Memory中，然后再进行传输
    CHECK(cudaMemcpy(device_mem, host_pinned_mem, nbytes, cudaMemcpyHostToDevice));

    // 从设备向主机传输数据
    CHECK(cudaMemcpy(host_pinned_mem, device_mem, nbytes, cudaMemcpyDeviceToHost));

    // 释放设备内存和固定主机内存
    CHECK(cudaFree(device_mem));
    CHECK(cudaFreeHost(host_pinned_mem));

    CHECK(cudaDeviceReset());

    return 0;
}